python c PyLongObject定义及实现2

/*根据长整型生成python PyLongObject对象*/
PyObject* PyLong_FromLong(long v) 

通过这个函数我们来了解python是怎么构造一个PyLongObject对象。 PyLong_FromLong函数源码

/*在64位系统中PyLong_SHIFT=30,*/
#define PyLong_BASE    ((digit)1 << PyLong_SHIFT)
#define PyLong_MASK    ((digit)(PyLong_BASE - 1))
PyObject *
PyLong_FromLong(long ival)
{
    PyLongObject *v;
    unsigned long abs_ival;
    unsigned long t;  /* unsigned so >> doesn't propagate sign bit */
    int ndigits = 0;
    int negative = 0;

    if (ival < 0) {
        /* if LONG_MIN == -LONG_MAX-1 (true on most platforms) then
           ANSI C says that the result of -ival is undefined when ival
           == LONG_MIN.  Hence the following workaround. */
        abs_ival = (unsigned long)(-1-ival) + 1;
        negative = 1;
    }
    else {
        abs_ival = (unsigned long)ival;
    }

    /* Count the number of Python digits.
       We used to pick 5 ("big enough for anything"), but that's a
       waste of time and space given that 5*15 = 75 bits are rarely
       needed. */
    t = abs_ival;
    while (t) {
        ++ndigits;
        t >>= PyLong_SHIFT;
    }
    v = _PyLong_New(ndigits);//为PyLongObject对象分配内存
    if (v != NULL) {
        digit *p = v->ob_digit;
        v->ob_size = negative ? -ndigits : ndigits;
        t = abs_ival;
        while (t) {
            *p++ = (digit)(t & PyLong_MASK);
            t >>= PyLong_SHIFT;
        }
    }
    return (PyObject *)v;
}

转换成可以单独执行的C代码

#include <stdio.h>
#include <math.h>

#define base ((unsigned int)1 <<30)
#define mask ((unsigned int)(base-1))

int main(int argc, char *argv[]){
    unsigned int abs_ival;
    unsigned int t;
    int ndigits = 0;
    int i;
    abs_ival = (1<<32) - 1 ;
    t = abs_ival;
    while(t){
        ++ndigits;
        t >>=30;
    }
    unsigned int ob_digit[ndigits];
    unsigned int *p = ob_digit;
    t = abs_ival;
    while(t){
        *p++ = (unsigned int)(t & mask);
        t >>= 30;
    }

    for(i=0;i<ndigits;i++)
        printf("%u\t",ob_digit[i]);
    printf("\n");
   abs_ival = 0; 
   //根据数组ob_digit[]中的值,打印出原始值
   for(i=0;i<ndigits;i++)
       abs_ival += ob_digit[i] * pow(2,30*i);//or:abs_ival += ob_digit[i]*(1<<(30*i));

   printf("%u\n",abs_ival);

   return 0;
}
gcc longo.c -lm //不加-lm则会报错
out:
1073741823  3   
4294967295

base = 0x40000000 mask = 0x3fffffff abs_ival = 0xffffffff ob_digit中元素的最大值为(2**30)-1


?PyLong_SHIFT为什么是30。 Ref:python2.7源码